/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jxtaEssentials;

import java.util.logging.Level;
import net.jxta.document.*;
import net.jxta.id.ID;
import net.jxta.id.IDFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;
import java.util.logging.Logger;
import net.jxta.protocol.PipeAdvertisement;

/**
 *
 * @author Asistente
 */
public class FileAdvertisement extends Advertisement
        implements Comparable, Cloneable, Serializable {

    private ID id = ID.nullID;
    private String fileName;
    private PipeAdvertisement pipeAdv = null;
    private static final Logger LOG =
            Logger.getLogger(FileAdvertisement.class.getName());
    public final static String fileNameTag = "FileName";
    public final static String idTag = "ID";
    public final static String pipeAdvTag = "Tag";
    private final static String[] fields = {idTag, fileNameTag, pipeAdvTag};

    public PipeAdvertisement getPipeAdv() {
        return pipeAdv;
    }

    public void setPipeAdv(PipeAdvertisement pipeAdv) {
        this.pipeAdv = pipeAdv;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public FileAdvertisement() {
    }

    /**
     * Construct from a StructuredDocument
     *
     * @param root Root element
     */
    public FileAdvertisement(Element root) {
        TextElement doc = (TextElement) root;
        if (!getAdvertisementType().equals(doc.getName())) {
            throw new IllegalArgumentException("Could not construct : "
                    + getClass().getName() + "from doc containing a " + doc.getName());
        }
        initialize(doc);
    }

    /**
     * Construct a doc from InputStream
     *
     * @param stream the underlying input stream.
     * @throws IOException if an I/O error occurs.
     */
    public FileAdvertisement(InputStream stream) throws IOException {
        StructuredTextDocument doc = (StructuredTextDocument) StructuredDocumentFactory.newStructuredDocument(MimeMediaType.XMLUTF8, stream);
        initialize(doc);
    }

    /**
     * Intialize a System advertisement from a portion of a structured document.
     *
     * @param root document root
     */
    protected final void initialize(Element root) {
        if (!TextElement.class.isInstance(root)) {
            throw new IllegalArgumentException(getClass().getName()
                    + " only supports TextElement");
        }
        TextElement doc = (TextElement) root;
        if (!doc.getName().equals(getAdvertisementType())) {
            throw new IllegalArgumentException("Could not construct : "
                    + getClass().getName() + "from doc containing a "
                    + doc.getName());
        }
        Enumeration elements = doc.getChildren();
        while (elements.hasMoreElements()) {
            TextElement elem = (TextElement) elements.nextElement();
            if (!handleElement(elem)) {
                LOG.log(Level.WARNING, "Unhandleded element ''{0}'' in {1}", 
                            new Object[]{elem.getName(), doc.getName()});
            }
        }
    }

    /**
     * Process an individual element from the document.
     *
     * @param elem the element to be processed.
     * @return true if the element was recognized, otherwise false.
     */
    protected boolean handleElement(TextElement elem) {
        if (elem.getName().equals(idTag)) {
            try {
                URI idTmp = new URI(elem.getTextValue());
                setID(IDFactory.fromURI(idTmp));
            } catch (URISyntaxException badID) {
                throw new IllegalArgumentException("unknown ID format in advertisement: "
                        + elem.getTextValue());
            } catch (ClassCastException badID) {
                throw new IllegalArgumentException("Id is not a known id type: "
                        + elem.getTextValue());
            }
            return true;
        }
        if (elem.getName().equals(fileNameTag)) {
            setFileName(elem.getTextValue());
        }
        if (elem.getName().equals(pipeAdvTag)){
            setPipeAdv(null);
        }
        return false;
    }

    @Override
    public Document getDocument(MimeMediaType asMimeType) {
        StructuredDocument adv = StructuredDocumentFactory.newStructuredDocument(asMimeType,
                getAdvertisementType());
        if (adv instanceof Attributable) {
            ((Attributable) adv).addAttribute("xmlns:jxta", "http://jxta.org");
        }
        Element e;
        e = adv.createElement(idTag, getID().toString());
        adv.appendChild(e);
        e = adv.createElement(fileNameTag, getFileName().trim());
        adv.appendChild(e);
        return adv;
    }

    @Override
    public ID getID() {
        return (id == null ? null : id);
    }

    public void setID(ID id) {
        this.id = (id == null ? null : id);
    }

    @Override
    public String[] getIndexFields() {
        return fields;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof FileAdvertisement) {
            FileAdvertisement adv = (FileAdvertisement) obj;
            return getID().equals(adv.getID());
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 29 * hash + (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }

    public int compareTo(Object other) {
        return getID().toString().compareTo(other.toString());
    }

    /**
     * All messages have a type (in xml this is &#0033;doctype) which
     * identifies the message
     *
     * @return String "jxta:AdvertisementTutorial"
     */
    public static String getAdvertisementType() {
        return "jxta:FileAdvertisement";
    }

    /**
     * Instantiator
     */
    public static class Instantiator implements AdvertisementFactory.Instantiator {

        /**
         * Returns the identifying type of this Advertisement.
         *
         * @return String the type of advertisement
         */
        public String getAdvertisementType() {
            return FileAdvertisement.getAdvertisementType();
        }

        /**
         * Constructs an instance of <CODE>Advertisement</CODE> matching the
         * type specified by the <CODE>advertisementType</CODE> parameter.
         *
         * @return The instance of <CODE>Advertisement</CODE> or null if it
         * could not be created.
         */
        public Advertisement newInstance() {
            return new FileAdvertisement();
        }

        /**
         * Constructs an instance of <CODE>Advertisement</CODE> matching the
        }
         * * type specified by the <CODE>advertisementType</CODE> parameter.
         *
         * @param root Specifies a portion of a StructuredDocument which will
         * be converted into an Advertisement.
         * @return The instance of <CODE>Advertisement</CODE> or null if it
         * could not be created.
         */
        public FileAdvertisement newInstance(net.jxta.document.Element root) {
            return new FileAdvertisement(root);
        }
    }

    public static void main(String args[]) {
// The following step is required and only need to be done once,
// without this step the AdvertisementFactory has no means of
// associating an advertisement name space with the proper obect
// in this cast the AdvertisementTutorial
        AdvertisementFactory.registerAdvertisementInstance(
                FileAdvertisement.getAdvertisementType(),
                new FileAdvertisement.Instantiator());
        FileAdvertisement advFile = new FileAdvertisement();
        advFile.setID(ID.nullID);
        advFile.setFileName("warez.rar");
        System.out.println(advFile.toString());
    }
}
